.TH std::operator+(std::basic_string) 3 "2024.06.10" "http://cppreference.com" "C++ Standard Libary"
.SH NAME
std::operator+(std::basic_string) \- std::operator+(std::basic_string)

.SH Synopsis
   Defined in header <string>
   template< class CharT, class Traits, class Alloc >

   std::basic_string<CharT,Traits,Alloc>                              \fB(1)\fP  (constexpr
       operator+( const std::basic_string<CharT,Traits,Alloc>& lhs,        since C++20)

                  const std::basic_string<CharT,Traits,Alloc>& rhs );
   template< class CharT, class Traits, class Alloc >

   std::basic_string<CharT,Traits,Alloc>                              \fB(2)\fP  (constexpr
       operator+( const std::basic_string<CharT,Traits,Alloc>& lhs,        since C++20)

                  const CharT* rhs );
   template< class CharT, class Traits, class Alloc >

   std::basic_string<CharT,Traits,Alloc>                              \fB(3)\fP  (constexpr
       operator+( const std::basic_string<CharT,Traits,Alloc>& lhs,        since C++20)

                  CharT rhs );
   template< class CharT, class Traits, class Alloc >

   constexpr std::basic_string<CharT,Traits,Alloc>                         (since
       operator+( const std::basic_string<CharT,Traits,Alloc>& lhs,   \fB(4)\fP  C++26)


    std::type_identity_t<std::basic_string_view<CharT,Traits>> rhs );
   template< class CharT, class Traits, class Alloc >

   std::basic_string<CharT,Traits,Alloc>                              \fB(5)\fP  (constexpr
       operator+( const CharT* lhs,                                        since C++20)

                  const std::basic_string<CharT,Traits,Alloc>& rhs );
   template< class CharT, class Traits, class Alloc >

   std::basic_string<CharT,Traits,Alloc>                              \fB(6)\fP  (constexpr
       operator+( CharT lhs,                                               since C++20)

                  const std::basic_string<CharT,Traits,Alloc>& rhs );
   template< class CharT, class Traits, class Alloc >

   constexpr std::basic_string<CharT,Traits,Alloc>                         (since
       operator+(                                                     \fB(7)\fP  C++26)
   std::type_identity_t<std::basic_string_view<CharT,Traits>> lhs,

                  const std::basic_string<CharT,Traits,Alloc>& rhs );
   template< class CharT, class Traits, class Alloc >
                                                                           (since
   std::basic_string<CharT,Traits,Alloc>                              \fB(8)\fP  C++11)
       operator+( std::basic_string<CharT,Traits,Alloc>&& lhs,             (constexpr
                                                                           since C++20)
                  std::basic_string<CharT,Traits,Alloc>&& rhs );
   template< class CharT, class Traits, class Alloc >
                                                                           (since
   std::basic_string<CharT,Traits,Alloc>                              \fB(9)\fP  C++11)
       operator+( std::basic_string<CharT,Traits,Alloc>&& lhs,             (constexpr
                                                                           since C++20)
                  const std::basic_string<CharT,Traits,Alloc>& rhs );
   template< class CharT, class Traits, class Alloc >
                                                                           (since
   std::basic_string<CharT,Traits,Alloc>                              \fB(10)\fP C++11)
       operator+( std::basic_string<CharT,Traits,Alloc>&& lhs,             (constexpr
                                                                           since C++20)
                  const CharT* rhs );
   template< class CharT, class Traits, class Alloc >
                                                                           (since
   std::basic_string<CharT,Traits,Alloc>                              \fB(11)\fP C++11)
       operator+( std::basic_string<CharT,Traits,Alloc>&& lhs,             (constexpr
                                                                           since C++20)
                  CharT rhs );
   template< class CharT, class Traits, class Alloc >

   constexpr std::basic_string<CharT,Traits,Alloc>                         (since
       operator+( std::basic_string<CharT,Traits,Alloc>&& lhs,        \fB(12)\fP C++26)


    std::type_identity_t<std::basic_string_view<CharT,Traits>> rhs );
   template< class CharT, class Traits, class Alloc >
                                                                           (since
   std::basic_string<CharT,Traits,Alloc>                              \fB(13)\fP C++11)
       operator+( const std::basic_string<CharT,Traits,Alloc>& lhs,        (constexpr
                                                                           since C++20)
                  std::basic_string<CharT,Traits,Alloc>&& rhs );
   template< class CharT, class Traits, class Alloc >
                                                                           (since
   std::basic_string<CharT,Traits,Alloc>                              \fB(14)\fP C++11)
       operator+( const CharT* lhs,                                        (constexpr
                                                                           since C++20)
                  std::basic_string<CharT,Traits,Alloc>&& rhs );
   template< class CharT, class Traits, class Alloc >
                                                                           (since
   std::basic_string<CharT,Traits,Alloc>                              \fB(15)\fP C++11)
       operator+( CharT lhs,                                               (constexpr
                                                                           since C++20)
                  std::basic_string<CharT,Traits,Alloc>&& rhs );
   template< class CharT, class Traits, class Alloc >

   constexpr std::basic_string<CharT,Traits,Alloc>                         (since
       operator+(                                                     \fB(16)\fP C++26)
   std::type_identity_t<std::basic_string_view<CharT,Traits>> lhs,

                  std::basic_string<CharT,Traits,Alloc>&& rhs );

   Returns a string containing characters from lhs followed by the characters from rhs.
   Equivalent to:

   1,2) std::basic_string<CharT, Traits, Allocator> r = lhs; r.append(rhs); return r;
   3) std::basic_string<CharT, Traits, Allocator> r = lhs; r.push_back(rhs); return r;
   4) std::basic_string<CharT, Traits, Allocator> r = lhs; r.append(rhs); return r;
   5) std::basic_string<CharT, Traits, Allocator> r = rhs; r.insert(0, lhs); return r;
   6) std::basic_string<CharT, Traits, Allocator> r = rhs; r.insert(r.begin(), lhs);
   return r;
   7) std::basic_string<CharT, Traits, Allocator> r = rhs; r.insert(0, lhs); return r;
   8) lhs.append(rhs); return std::move(lhs); except that both lhs and rhs are left in
   valid but unspecified states. If lhs and rhs have equal allocators, the
   implementation can move from either.
   9,10) lhs.append(rhs); return std::move(lhs);
   11) lhs.push_back(rhs); return std::move(lhs);
   12) lhs.append(rhs); return std::move(lhs);
   13,14) rhs.insert(0, lhs); return std::move(rhs);
   15) rhs.insert(rhs.begin(), lhs); return std::move(rhs);
   16) rhs.insert(0, lhs); return std::move(rhs);

The allocator used for the result is:

1-4)
std::allocator_traits<Alloc>::select_on_container_copy_construction(lhs.get_allocator())
5-7)
std::allocator_traits<Alloc>::select_on_container_copy_construction(rhs.get_allocator())
8-12) lhs.get_allocator()
13-16) rhs.get_allocator()
                                                                                         (since
In other words:                                                                          C++11)

  * If one operand is a basic_string rvalue, its allocator is used.
  * Otherwise, select_on_container_copy_construction is used on the allocator of the
    lvalue basic_string operand.

In each case, the left operand is preferred when both are basic_strings of the same
value category.

For (8-16), all rvalue basic_string operands are left in valid but unspecified states.

.SH Parameters

         string
   lhs - , string view
         (since C++26), character, or pointer to the first character in a
         null-terminated array
         string
   rhs - , string view
         (since C++26), character, or pointer to the first character in a
         null-terminated array

.SH Return value

   A string containing characters from lhs followed by the characters from rhs
   , using the allocator determined as above
   \fI(since C++11)\fP.

.SH Notes

operator+ should be used with great caution when stateful allocators are involved
(such as when std::pmr::string is used)
\fI(since C++17)\fP. Prior to P1165R1, the allocator used for the result was determined by
historical accident and can vary from overload to overload for no apparent reason.
Moreover, for (1-5), the allocator propagation behavior varies across major standard
library implementations and differs from the behavior depicted in the standard.

Because the allocator used by the result of operator+ is sensitive to value category,
operator+ is not associative with respect to allocator propagation:

using my_string = std::basic_string<char, std::char_traits<char>, my_allocator<char>>;
my_string cat();
const my_string& dog();                                                                     (since
                                                                                            C++11)
my_string meow = /* ... */, woof = /* ... */;
meow + cat() + /* ... */; // uses select_on_container_copy_construction on meow's allocator
woof + dog() + /* ... */; // uses allocator of dog()'s return value instead

meow + woof + meow; // uses select_on_container_copy_construction on meow's allocator
meow + (woof + meow); // uses SOCCC on woof's allocator instead

For a chain of operator+ invocations, the allocator used for the ultimate result may be
controlled by prepending an rvalue basic_string with the desired allocator:

// use my_favorite_allocator for the final result
my_string(my_favorite_allocator) + meow + woof + cat() + dog();

For better and portable control over allocators, member functions like append, insert, and
operator+= should be used on a result string constructed with the desired allocator.

   The usage of std::type_identity_t as parameter in overloads \fB(4)\fP, \fB(7)\fP, \fB(12)\fP,
   and \fB(16)\fP ensures that an object of type std::basic_string<CharT, Traits,
   Allocator> can always be concatenated to an object of a type T with an
   implicit conversion to std::basic_string_view<CharT, Traits>, and vice versa, (since
   as per overload resolution rules.                                             C++26)

    Feature-test macro   Value    Std                   Feature
   __cpp_lib_string_view 202403 (C++26) Concatenation of strings and string
                                        views, overloads \fB(4)\fP, \fB(7)\fP, \fB(12)\fP, \fB(16)\fP

.SH Example


// Run this code

 #include <iostream>
 #include <string>
 #include <string_view>

 int main()
 {
     std::string s1 = "Hello";
     std::string s2 = "world";
     const char* end = "!\\n";
     std::cout << s1 + ' ' + s2 + end;

     std::string_view water{" Water"};
     #if __cpp_lib_string_view >= 202403
     std::cout << s1 + water + s2 << end; // overload (4), then (1)
     #else
     std::cout << s1 + std::string(water) + s2 << end; // OK, but less efficient
     #endif
 }

.SH Output:

 Hello world!
 Hello Waterworld!

   Defect reports

   The following behavior-changing defect reports were applied retroactively to
   previously published C++ standards.

     DR    Applied to            Behavior as published               Correct behavior
   P1165R1 C++11      allocator propagation is haphazard and       made more consistent
                      inconsistent

.SH See also

   operator+= appends characters to the end
              \fI(public member function)\fP
   append     appends characters to the end
              \fI(public member function)\fP
   insert     inserts characters
              \fI(public member function)\fP
